﻿using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Configuration;
using System.Reflection;

namespace FolderFileMenu
{
    public partial class OptionsForm : Form
    {
        Version curVersion = Assembly.GetExecutingAssembly().GetName().Version;
        static string thisPath = Assembly.GetExecutingAssembly().Location; // = Application.StartupPath;
        static string thisFolder = Path.GetDirectoryName(thisPath);
        static string folderName = Path.GetFileName(thisFolder); // = new DirectoryInfo(thisFolder).Name;
        static string exeName = Path.GetFileNameWithoutExtension(thisPath); // (Assembly.GetExecutingAssembly().CodeBase);

        public OptionsForm()
        {
            InitializeComponent();
            try
            {
                Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); // if file.exists: Program.cs
                if (config.AppSettings.Settings["FileScheme"] == null)
                {
                    config.AppSettings.Settings.Add("FileScheme", "*.*");
                    config.Save(ConfigurationSaveMode.Modified);
                }
                textBoxFileScheme.Text = config.AppSettings.Settings["FileScheme"].Value;

                if (config.AppSettings.Settings["ExcludeFiles"] == null)
                {
                    config.AppSettings.Settings.Add("ExcludeFiles", "");
                    config.Save(ConfigurationSaveMode.Modified);
                }
                textBoxExcludeFiles.Text = config.AppSettings.Settings["ExcludeFiles"].Value;

                if (config.AppSettings.Settings["SubFolders"] == null)
                {
                    config.AppSettings.Settings.Add("SubFolders", "0");
                    config.Save(ConfigurationSaveMode.Modified);
                }
                checkBoxSubfolders.Checked = config.AppSettings.Settings["SubFolders"].Value.Equals("1") ? true : false;

                if (config.AppSettings.Settings["ExcludeFolders"] == null)
                {
                    config.AppSettings.Settings.Add("ExcludeFolders", "");
                    config.Save(ConfigurationSaveMode.Modified);
                }
                textBoxExcludeFolders.Text = config.AppSettings.Settings["ExcludeFolders"].Value;

                if (config.AppSettings.Settings["SortLastModified"] == null)
                {
                    config.AppSettings.Settings.Add("SortLastModified", "0");
                    config.Save(ConfigurationSaveMode.Modified);
                }
                checkBoxSortLastModified.Checked = config.AppSettings.Settings["SortLastModified"].Value.Equals("1") ? true : false;

                if (config.AppSettings.Settings["DesktopShortcut"] == null)
                {
                    config.AppSettings.Settings.Add("DesktopShortcut", "1");
                    config.Save(ConfigurationSaveMode.Modified);
                }
                checkBoxShortcut.Checked = config.AppSettings.Settings["DesktopShortcut"].Value.Equals("1") ? true : false;

                if (config.AppSettings.Settings["IconPath"] == null)
                {
                    config.AppSettings.Settings.Add("IconPath", "");
                    config.Save(ConfigurationSaveMode.Modified);
                }
                textBoxIconFile.Text = config.AppSettings.Settings["IconPath"].Value;
                checkBoxIconFile.Checked = File.Exists(textBoxIconFile.Text) ? true : false;

                if (config.AppSettings.Settings["IconIndex"] == null)
                {
                    config.AppSettings.Settings.Add("IconIndex", "0");
                    config.Save(ConfigurationSaveMode.Modified);
                }
                comboBoxIconIndex.Text = config.AppSettings.Settings["IconIndex"].Value;
                ConfigurationManager.RefreshSection("appSettings"); // wg. nachfolgendem Close() eingentlich nicht erforderlich
            }// you don't need to Close/Dispose. The Configuration class returned by the OpenExeConfiguration static method doesn't implement IDisposable nor it has any Close method 
            catch (ConfigurationErrorsException) { MessageBox.Show("Error writing app settings", thisFolder, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); }

            string strText = thisFolder;
            int maxInt = 50;
            if (strText.Length > maxInt)
            {
                strText = strText.Substring(strText.Length - maxInt);
                strText = strText.Substring(strText.IndexOf(@"\"));
                strText = string.Concat("...", strText);
            }
            Text = strText;
        }

        private void buttonOK_Click(object sender, EventArgs e)
        {// Trim entfernt alle führenden und nachgestellten Vorkommen; Replace entfernt innerhalb des Strings
            char[] charsToTrim = { ' ', '.', ',', ';', '"', '\'', '\\' }; // Leerzeichen, Punkt, Komma, Semikolon, Anführungsstriche, ', \
            try
            {
                Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                config.AppSettings.Settings["FileScheme"].Value = textBoxFileScheme.Text.Trim(charsToTrim).Replace(";", ",");
                config.AppSettings.Settings["ExcludeFiles"].Value = textBoxExcludeFiles.Text.Trim(charsToTrim).Replace(";", ",").Replace(Path.DirectorySeparatorChar.ToString(), ", ");
                config.AppSettings.Settings["SubFolders"].Value = checkBoxSubfolders.Checked ? "1" : "0";
                config.AppSettings.Settings["ExcludeFolders"].Value = textBoxExcludeFolders.Text.Trim(charsToTrim).Replace(";", ",").Replace(Path.DirectorySeparatorChar.ToString(), ", ");
                config.AppSettings.Settings["SortLastModified"].Value = checkBoxSortLastModified.Checked ? "1" : "0";
                config.AppSettings.Settings["DesktopShortcut"].Value = checkBoxShortcut.Checked ? "1" : "0";
                config.AppSettings.Settings["IconPath"].Value = checkBoxIconFile.Checked && File.Exists(textBoxIconFile.Text.Trim(charsToTrim)) ? textBoxIconFile.Text.Trim(charsToTrim) : "";
                config.AppSettings.Settings["IconIndex"].Value = comboBoxIconIndex.Text;
                config.Save(ConfigurationSaveMode.Modified); // Speichern aller Änderungen
                ConfigurationManager.RefreshSection("appSettings"); // wg. nachfolgendem Close() eingentlich nicht erforderlich
            }// you don't need to Close/Dispose. The Configuration class returned by the OpenExeConfiguration static method doesn't implement IDisposable nor it has any Close method 
            catch (ConfigurationErrorsException) { MessageBox.Show("Error writing app settings", thisFolder, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); }
            Close(); //Application.Exit(); // Hauptformular wird durch "finally: Close()" geschlossen
        }

        private void buttonCancel_Click(object sender, EventArgs e) { Close(); }

        private void buttonAbout_Click(object sender, EventArgs e)
        {
            string l1Text = exeName +
@" is free software: you can redistribute
it and/or modify it under the terms of the GNU Lesser Public
License as published by the Free Software Foundation, either
version 3 of the license, or (at your option) any later version.";
            string l2Text = exeName +
@" is distributed in the hope that it will
be useful, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU Lesser Public License for
more details. <http://www.gnu.org/licenses/>.";

            string mbText = String.Concat("Programmversion: " + curVersion + ", Build vom "
                  + RetrieveLinkerTimestamp().ToString("d.M.yyyy") + Environment.NewLine
                  + "Author/Copyright: Dr. Wilhelm Happe, Kiel" + Environment.NewLine + Environment.NewLine
                  + "¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯" + Environment.NewLine
                  + l1Text + Environment.NewLine + l2Text);
            MessageBox.Show(mbText, Text, MessageBoxButtons.OK, MessageBoxIcon.None);
        }

        private DateTime RetrieveLinkerTimestamp() // lässt sich nicht in Utilities.cs verlagern
        {
            string filePath = Assembly.GetCallingAssembly().Location;
            const int c_PeHeaderOffset = 60;
            const int c_LinkerTimestampOffset = 8;
            byte[] b = new byte[2048];
            Stream s = null;
            try
            {
                s = new FileStream(filePath, FileMode.Open, FileAccess.Read);
                s.Read(b, 0, 2048);
            }
            finally { if (s != null) s.Close(); }
            int i = BitConverter.ToInt32(b, c_PeHeaderOffset);
            int secondsSince1970 = BitConverter.ToInt32(b, i + c_LinkerTimestampOffset);
            DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0);
            dt = dt.AddSeconds(secondsSince1970);
            dt = dt.AddHours(TimeZone.CurrentTimeZone.GetUtcOffset(dt).Hours);
            return dt;
        }

        private void buttonDesktopShortcut_Click(object sender, EventArgs e)
        {
            string iconPath = checkBoxIconFile.Checked ? textBoxIconFile.Text : thisPath;
            if (string.IsNullOrEmpty(iconPath))
            {
                textBoxIconFile.Focus();
                return;
            }
            string linkFileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), folderName + "-FileList.lnk");
            int x = 0;
            int.TryParse(comboBoxIconIndex.Text, out x);
            using (var shellShortcut = new ShellShortcut(linkFileName)
            {
                Path = thisPath, // Application.ExecutablePath,
                WorkingDirectory = thisFolder, // Application.StartupPath,
                Arguments = "",
                IconPath = File.Exists(iconPath) ? iconPath : thisPath,
                IconIndex = x,
                Description = "Hold down the shift key during startup to open the settings dialog.",
            })
                try
                {
                    shellShortcut.Save();
                    MessageBox.Show("The desktop shortcut has been created successfully:" + Environment.NewLine + linkFileName, thisFolder, MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                catch (Exception ex) { MessageBox.Show(ex.Message, thisFolder, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); }
                finally { buttonOK.Focus(); }
        }

        private void buttonIconFile_Click(object sender, EventArgs e)
        {
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                textBoxIconFile.Text = openFileDialog.FileName;
                GetIconFromFile(textBoxIconFile.Text);
                textBoxIconFile.Focus();
            }
        }

        private void checkBoxIconFile_CheckedChanged(object sender, EventArgs e)
        {
            textBoxIconFile.Enabled = buttonIconFile.Enabled = comboBoxIconIndex.Enabled = checkBoxIconFile.Checked;
            if (checkBoxIconFile.Checked && File.Exists(textBoxIconFile.Text))
            {
                GetIconFromFile(textBoxIconFile.Text);
            }
            else
            {
                if (pictureBoxShortcutIcon.Image != null) { pictureBoxShortcutIcon.Image.Dispose(); }
                pictureBoxShortcutIcon.Image = null;
                if (checkBoxIconFile.Checked) { textBoxIconFile.Text = ""; }
            }
        }

        private void comboBoxIconIndex_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (checkBoxIconFile.Checked && File.Exists(textBoxIconFile.Text))
            {
                if (GetIconFromFile(textBoxIconFile.Text) <= comboBoxIconIndex.SelectedIndex)
                {
                    comboBoxIconIndex.Text = "0";
                }
            }
            else
            {
                if (pictureBoxShortcutIcon.Image != null) { pictureBoxShortcutIcon.Image.Dispose(); }
                pictureBoxShortcutIcon.Image = null;
                comboBoxIconIndex.Text = "0";
            }
        }

        private int GetIconFromFile(string path)
        {// return value = number of icons contained in the specified file
            try
            {
                int x = 0;
                int.TryParse(comboBoxIconIndex.Text, out x);
                var result = NativeWin32.ExtractIconFromExe(path, true, x); // true => largeIcon
                pictureBoxShortcutIcon.Image = result.icon.ToBitmap();
                return result.total; // totalNumber
            }
            catch (Exception)
            {
                if (pictureBoxShortcutIcon.Image != null) { pictureBoxShortcutIcon.Image.Dispose(); }
                pictureBoxShortcutIcon.Image = null;
                comboBoxIconIndex.Text = "0";
                textBoxIconFile.Text = "ERROR: File contains no icon.";
                checkBoxIconFile.Checked = false;
                return 0;
            }
        }

        private void comboBoxIconIndex_KeyPress(object sender, KeyPressEventArgs e) { e.Handled = !char.IsDigit(e.KeyChar); }
        private void OptionsForm_Load(object sender, EventArgs e) { WindowState = FormWindowState.Normal; } // nur in Ausnahmen erforderlch (AutoHotkey: Run ,,, Max)
        private void OptionsForm_Shown(object sender, EventArgs e) { TopMost = false; BringToFront(); Activate(); }
        private void checkBoxSubfolders_CheckedChanged(object sender, EventArgs e) { textBoxExcludeFolders.Enabled = labelExcludeFolders.Enabled = checkBoxSubfolders.Checked; }

    }
}